﻿using System;
using System.Linq;
using System.Net;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Web;
using DotNetNuke.Entities.Users;
using DotNetNuke.Modules._2DoTasks.Components;
using DotNetNuke.Modules._2DoTasks.Components.Controllers;
using DotNetNuke.Modules._2DoTasks.Components.ExceptionHandling;
using DotNetNuke.Modules._2DoTasks.Components.ServiceRelated;

namespace DotNetNuke.Modules._2DoTasks.Services
{
    /// <summary>
    /// Services provided for the dnn 2dotasks module
    /// </summary>
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    public class DataService : IDataService
    {
        private const short PROJECT_MINLENGHT = 2;

        #region "IDataService Methods"

        #region "Project"

        /// <summary>
        /// Gets all the projects active with or the name starts like the parameter passed
        /// </summary>
        /// <param name="projectName">the project name</param>
        /// <param name="portalId">the dnn portalId</param>
        /// <returns>returns array of project names</returns>
        public string[] Project_GetByName(string projectName, int portalId)
        {
            try
            {
                //if the minimun lenght for the projectname wasn't reached, return null
                if (projectName.Trim().Length < PROJECT_MINLENGHT)
                    return null;

                UserInfo user = null;
                user = GetUserInfo(portalId);

                //get the projects
                using (UnitOfWork uof = new UnitOfWork(portalId, user))
                {
                    ProjectController prjController = new ProjectController(uof);
                    return prjController.GetStartsWith(projectName.Trim()).Select(p => p.Name).ToArray();
                }
            }
            catch (UnauthorizedAccessException)
            {
                ErrorData errorData = new ErrorData("UnauthorizedAccessException", "You are not authorized to use this service.");

                throw new WebFaultException<ErrorData>(errorData, HttpStatusCode.BadRequest);
            }
            catch (Exception exc)
            {
                ErrorData errorData = new ErrorData("UnknownException", exc.InnerException != null ? exc.InnerException.Message : exc.Message);

                throw new WebFaultException<ErrorData>(errorData, HttpStatusCode.BadRequest);
            }
        }

        #endregion "Project"

        #region "Task"

        /// <summary>
        /// Toggles the task status, between closed or open, depeding on the current status
        /// </summary>
        /// <param name="taskId">the id of the task to update</param>
        /// <param name="portalId">the portal id</param>
        public void Task_ToggleComplete(int taskId, int portalId)
        {
            try
            {
                UserInfo user = null;
                user = GetUserInfo(portalId);

                //get the projects
                using (UnitOfWork uof = new UnitOfWork(portalId, user))
                {
                    TaskController tskController = new TaskController(uof);

                    //get task

                    var task = tskController.Get(taskId);
                    if (task.TaskStatus == (int)SharedEnum.TaskStatus.Closed)
                    {
                        tskController.SetStatus(taskId, SharedEnum.TaskStatus.Open, null);
                    }
                    else
                        tskController.SetStatus(taskId, SharedEnum.TaskStatus.Closed, DateTime.Now);
                }
            }
            catch (TaskValidationException exc)
            {
                TaskController.UpdateStatus status =
                            (TaskController.UpdateStatus)Enum.Parse(typeof(TaskController.UpdateStatus), exc.ErrorCode().ToString());

                ErrorData errorData = new ErrorData(status.ToString(), exc.Message);

                throw new WebFaultException<ErrorData>(errorData, HttpStatusCode.BadRequest);
            }
            catch (UnauthorizedAccessException)
            {
                ErrorData errorData = new ErrorData("UnauthorizedAccessException", "You are not authorized to use this service.");

                throw new WebFaultException<ErrorData>(errorData, HttpStatusCode.BadRequest);
            }
            catch (Exception exc)
            {
                ErrorData errorData = new ErrorData("UnknownException", exc.InnerException != null ? exc.InnerException.Message : exc.Message);

                throw new WebFaultException<ErrorData>(errorData, HttpStatusCode.BadRequest);
            }
        }

        #region "Sub Task"

        /// <summary>
        /// Toggles the task status, between closed or open, depending if completed date is set or not
        /// </summary>
        /// <param name="taskId">the parent task id</param>
        /// <param name="subTaskId">the subtask id</param>
        /// <param name="portalId">the portl id</param>
        public void TaskSubTask_ToggleComplete(int taskId, int subTaskId, int portalId)
        {
            try
            {
                UserInfo user = null;
                user = GetUserInfo(portalId);

                //get the projects
                using (UnitOfWork uof = new UnitOfWork(portalId, user))
                {
                    TaskSubTaskController tskSubTaskController = new TaskSubTaskController(uof, taskId);

                    //get task

                    var task = tskSubTaskController.Get(subTaskId);
                    tskSubTaskController.ToggleComplete(task);
                }
            }
            catch (TaskSubTaskValidationException exc)
            {
                TaskSubTaskController.UpdateStatus status =
                            (TaskSubTaskController.UpdateStatus)Enum.Parse(typeof(TaskSubTaskController.UpdateStatus), exc.ErrorCode().ToString());

                ErrorData errorData = new ErrorData(status.ToString(), exc.Message);

                throw new WebFaultException<ErrorData>(errorData, HttpStatusCode.BadRequest);
            }
            catch (UnauthorizedAccessException)
            {
                ErrorData errorData = new ErrorData("UnauthorizedAccessException", "You are not authorized to use this service.");

                throw new WebFaultException<ErrorData>(errorData, HttpStatusCode.BadRequest);
            }
            catch (Exception exc)
            {
                ErrorData errorData = new ErrorData("UnknownException", exc.InnerException != null ? exc.InnerException.Message : exc.Message);

                throw new WebFaultException<ErrorData>(errorData, HttpStatusCode.BadRequest);
            }
        }

        /// <summary>
        /// Updates the sub task order in the list
        /// </summary>
        /// <param name="taskId">the parent task id</param>
        /// <param name="subTaskId">the subtask id</param>
        /// <param name="portalId">the portl id</param>
        /// <param name="order">new order position</param>
        public void TaskSubTask_UpdateOrder(int taskId, int subTaskId, int portalId, int order)
        {
            try
            {
                UserInfo user = null;
                user = GetUserInfo(portalId);

                //get the projects
                using (UnitOfWork uof = new UnitOfWork(portalId, user))
                {
                    TaskSubTaskController tskSubTaskController = new TaskSubTaskController(uof, taskId);

                    //get task

                    var task = tskSubTaskController.Get(subTaskId);
                    tskSubTaskController.UpdateOrder(task, order);
                }
            }
            catch (TaskSubTaskValidationException exc)
            {
                TaskSubTaskController.UpdateStatus status =
                            (TaskSubTaskController.UpdateStatus)Enum.Parse(typeof(TaskSubTaskController.UpdateStatus), exc.ErrorCode().ToString());

                ErrorData errorData = new ErrorData(status.ToString(), exc.Message);

                throw new WebFaultException<ErrorData>(errorData, HttpStatusCode.BadRequest);
            }
            catch (UnauthorizedAccessException)
            {
                ErrorData errorData = new ErrorData("UnauthorizedAccessException", "You are not authorized to use this service.");

                throw new WebFaultException<ErrorData>(errorData, HttpStatusCode.BadRequest);
            }
            catch (Exception exc)
            {
                ErrorData errorData = new ErrorData("UnknownException", exc.InnerException != null ? exc.InnerException.Message : exc.Message);

                throw new WebFaultException<ErrorData>(errorData, HttpStatusCode.BadRequest);
            }
        }

        #endregion "Sub Task"

        #endregion "Task"

        #endregion "IDataService Methods"

        #region "Aux Functions"

        /// <summary>
        /// Evaluates the current user that is making the request
        /// </summary>
        /// <param name="portalId">the dnn portal id</param>
        /// <returns>returns the userinfo</returns>
        private static UserInfo GetUserInfo(int portalId)
        {
            UserInfo user = null;
            if (HttpContext.Current.User.Identity.IsAuthenticated &&
                (user = UserController.GetUserByName(portalId, HttpContext.Current.User.Identity.Name)) != null)
            {
                return user;
            }
            else
                throw new UnauthorizedAccessException();
        }

        #endregion "Aux Functions"
    }
}